An elliptic curve everyone can trust.
Time has come to get rid of arbitrary choices.
By using publicly verifiable randomness produced in February 2016 by many national lotteries from all around the world, we propose to generate a cryptographically secure elliptic curve for the ECDH cryptosystem as an alternative to the NIST P-256 and the Curve25519 curves.
It is designed so that nobody (even us!) can put a trap in it.
Get the full paper Get the source code » #MDCurve on Twitter
Today most of elliptic-curve cryptography relies on the same set of curves: ANSSI FRP256v1, NIST P-256, NIST P-384, Curve25519, secp256k1, brainpoolP256t1, Curve1174 and a few others.
However, several of these curves parameters generation processes contain unjustified choices, specific constants or specific hash algorithms. Examples include the NIST P256 curve, whose parameters are derived from an unjustified seed (C49D3608 86E70493 6A6678E1 139D26B7 819F7E90), and the ANSSI FRP256v1 curve, for which no justification whatsoever is provided. The infamous Dual-EC-DRGB story legitimates the concerns many specialists have about the use of arbitrary choices.
I no longer trust the constants.
Of course, one should not conclude that cryptographic algorithms using similar constants are systematically insecure (certainly, some designers are honest!) and we will not dispute the right to trust those algorithms. Yet, in the perspective of eventually obtaining a legitimately trusted cryptographic algorithm by everybody, we believe that every future standard should rule out any cryptographic design involving arbitrary choices.
Choosing security and inspiring public trust above all.
The generation of elliptic curve parameters can be split into several parts:
Any choice of elliptic curve parameters should be performed in a justifiable, systematic, and comprehensive way. In addition to providing an algorithmic description on paper, we believe that one should also provide readable and executable code, and use an unimpeachable and publicly-verifiable entropy source.
In our technical paper, we describe a deterministic procedure to generate a cryptographically secure elliptic curve from a random seed. To the best of our knowledge, any curve generated through our methodology is secure (and in particular, meets all the SafeCurves criteria).
In addition to the technical paper, we publish and commit on the source code implementing our whole methodology, i.e. both the seed extraction algorithm and the elliptic curve parameters generation procedure.
By carefully selecting and combining many future lottery draws, we obtain an unpredictable, unbiased, publicly observable, and archived entropy source, that is easily verifiable in the future.
Nobody can predict what seed will be produced by those draws, even us!
The Million Dollar Curve.
On this website, we use the methodology described in our technical paper to generate an elliptic curve, that we call the Million Dollar Curve, as an alternative to curves P-256 and Curve25519 for the ECDH cryptosystem.
More precisely, we provide a tutorial that describes the whole process of generating an elliptic curve called the Three Cents Curve based on lottery draws from October 2015. Our methodology will then be fully instantiated to generate the Million Dollar Curve: we will commit on the design and the list of draws in January 2016, and the curve MDCurve201601 (Million Dollar Curve of January 2016) will be generated using lottery draws from February 2016.
In order for the Million Dollar Curve to inspire confidence to the greatest number, we want to integrate comments we receive in the methodology before committing on the methodology and the entropy source we will use. Please drop us an email and we will gladly listen.
Code overview
We provide 5 scripts, written in Python 3, that implement the whole methodology described in the technical paper:
01_draws_to_seed.py
takes as an input the path to a text file containing an ordered list of lottery draws, the quantity of entropy to be extracted from those draws (in a format described in the tutorial), and the number of lone bits to add. It outputs a JSON file containing the following parameters:
02_generate_bbs_parameters.py
takes as an input an integer min_prime_bitsize and a JSON file containing a seed and its upper bound. Typically, the input JSON file results from an execution of the previous script. It outputs a JSON file containing the following parameters:
03_generate_prime_field_using_bbs.py
takes as an input an integer prime_size and a JSON file containing the parameters of BBS. Typically, the input JSON file results from an execution of the previous script. It outputs a JSON file containing the following parameters:
04_generate_curve_using_bbs.py
takes as an input a JSON file containing the parameters of BBS and a prime p. It outputs a JSON file containing the following parameters:
--start
and --max_nbr_of_tests
that provide basic support for launching several instances of this script in parallel:
--start START
allows to start the search for a good candidate from the candidate number START
.--max_nbr_of_tests MAX_NBR_OF_TESTS
allows to make the script exit after MAX_NBR_OF_TESTS
candidates (unless a good candidate is found).
--fast
allows to discard bad candidates much faster by taking advantage of the fact that the Schoof–Elkies–Atkin algorithm implementation that we use to compute \(\#E(\mathbb{F}_p)\) can exit early if it detects that \(\#E(\mathbb{F}_p)\) will eventually be divisible by a small prime \(> 4\). When using this option, the cardinalities of bad candidates are not always output to the standard output.
05_prove_primes.py
When they require to test whether a number is prime, the four previous scripts only check that it is a pseudo-prime. This script implements a (generalized) Pocklington primality test to actually prove that the list of pseudo-primes given as an input are indeed primes.
Helpers
The 5 scripts rely on the following 4 helpers:
bbsengine.py
is a simple implementation of
BBS.pari_light_interface.py
is a simple interface to a few routines provided by the PARI C library. None of the functions defined in this file are actually called from the five main scripts. Rather, they are called in the following helper.subroutines.py
provides mathematical helper functions.utils.py
provides basic functions for printing information on screen, etc.Required libraries
Altogether, the scripts rely on several standard Python 3 libraries (argparse, bbsengine, ctypes, ctypes.util, datetime, json, math, os, re, subroutines, and sys) and on GMP, using
gmpy2. By means of the pari_light_interface.py
helper, they also make call to the PARI library (that should therefore be installed too). Since we use PARI to count point on elliptic curves, the seadata.tgz
must be installed too (this package is otherwise optional in most PARI implementations). To install this package, see
Optional PARI/GP packages.
These libraries should be readily available on Linux, and are easy to install on Mac OS X using
MacPorts. Installing the seadata.tgz
package for PARI is only slightly more involved. The source code we provide has been extensively tested with the 3.4.3 release of Python, the 2.0.7 version of gmpy2, and the 2.7.4 version of PARI.
Download
All the source code (scripts and helpers) is available on GitHub.
What is the Three Cents Curve and what is this tutorial about?
The Three Cents Curve is a toy cryptosystem, with realistic size parameters. The aim of this tutorial is to describe the whole process of generating this curve with our methodology. Note that the Three Cents Curve differs from the Two Cents Curve (which is the running example given in the technical paper).
Although the Three Cents Curve is a curve with 128 bit security, we firmly recommend not to use it for cryptographic purposes. The reason is that this curve was not generated using our full methodology (the reason why should be clear by the end of this tutorial). Yet, since it provides realistic sized parameters, it is close to being a full-fledged curve.
The tutorial
This tutorial will describe what would have been an acceptable process for generating this curve, in accordance with the methodology described in the technical paper. For this, Assume that today is...
As cryptographers willing to provide the community with a way of generating secure curves, we produce a document (a text file) describing:
On the 21st of June, 2015 (a date corresponding to \(t_0\) in the technical article), we commit on the design (i.e., on the 2015_06_three_cents_curve.txt
file) by:
2015_06_three_cents_curve.txt
. Although Let's Encrypt does not provide a dedicated way to timestamp digital documents (yet?), we suggest to ask for a certificate for the URL
which obviously contains the SHA256 of the Design text file (the dots in the hash are unfortunate but seems to be required for technical reasons). The notBefore
field of the certificate would then correspond to the timestamp (note that this field sometimes indicates a time that is a few minutes earlier than the date at which the URL was submitted, but this is not a problem for us).
#MDC201506 SHA256
c2ecf0526d6e17eebb77b1ce6d3a25c3d94b1d19860d767a61db4d7de9427af6 https://cryptoexperts.github.io/million-dollar-curve/2015_06_three_cents_curve.txt
2015_06_three_cents_curve.txt
certified in the Bitcoin blockchain (Worldwide), e.g., using Proof of Existence or
BTProof.
2015_06_three_cents_curve.txt
on GitHub (U.S.), together with the scripts.
2015_06_three_cents_curve.txt
on Bitbucket (Aus).
2015_06_three_cents_curve.txt
on DailyMotion (FR).
2015_06_three_cents_curve.txt
, and then publishing the sound on
SoundCloud (DE).
2015_06_three_cents_curve.txt
on
Flickr (U.S.)
As Standardizers willing to instantiate a cryptosystem according to the Design committed above, we produce a text file containing:
2015_06_three_cents_curve.txt
file).
seed
(under the assumption that the draws are uniformly distributed on their respective space).
On the the 23d of September, 2015 (a date corresponding to \(t_2\) in the technical article), we commit on the aforementioned 2015_09_three_cents_curve_standardization.txt
file, using similar means than those that were used to commit on the Design file.
Note that we took care to commit 2015_09_three_cents_curve_standardization.txt
at a time \(t_2
< t_3\), i.e., before the first draw of the list of 220 draws actually takes place.
During this period, the draws on which we committed on in Phase III take place, and the full list of result is gathered.
After the 13th of October, 2015, all the draws have taken place and anybody can update the list of the 220 draws on which we committed. The full list of results is available here: draws.txt. Here is an excerpt:
From this file anyone can execute the script 01_draws_to_seed.py
on which we committed, in order to extract entropy and compute the seed
:
./01_draws_to_seed.py draws.txt in_02.json 8192 --nbr_lone_bits 10
This produces the JSON file in_02.json
(available
here) contains the following parameters:
This JSON we obtained can now be used as an input the the first script provided by the committed Design:
./02_generate_bbs_parameters.py in_02.json in_03.json 2048
As explained in the technical paper and in the Source code section of this website, this script generates two strong strong primes of 2048 bits (at least) and a starting point for the
BBS PRNG. It saves these results the JSON file
in_03.json
available
here, with the following results:
Using these parameters, anyone can execute the second script provided by the Design, in order to generate the 256-bit prime \(p\) defining the finite field for the Three Cents Curve:
./03_generate_prime_field_using_bbs.py in_03.json in_04.json 256
This generates a JSON file named in_04.json
specifying the prime we were looking for, as well as an updated state of the
BBS PRNG. The file is available
here, it contains the following results:
Using these parameters, anyone can execute the third script provided by the Design, in order to generate the Edwards curve and the base point:
./04_generate_curve_using_bbs.py in_04.json out.json --fast
This generates a JSON file named out.json
specifying all the remaining parameters of the Three Cents Curve. Those parameters are obtained after 13879 bad candidates. The out.json
file is available
here, it contains (among others) the following parameters:
What is wrong with the Three Cents Curve?
Although the final curve we obtained has realistic sized parameters, you should not trust it. Indeed, this tutorial did not fully respect the methodology. In particular, the dates indicated in this tutorial are fictive. In reality, the Design of the Three Cents Curve was generated on the 21st of December, that is, at a time when all the draw results were actually known. As a consequence, you cannot be sure that we did not design the whole (deterministic) process as a function of those draw results, in order to make sure to eventually obtain a curve with a trapdoor. Moreover, we did not really commit on any of the text files. For this reason, we iterate our warning:
Hopefully, we plan to draw a proper curve, suited for cryptographic purposes. We call it, the Million Dollar Curve.
Introducing the Million Dollar Curve
The Million Dollar Curve will be an alternative to curves P-256 and Curve 25519 to instantiate the ECDH cryptosystem, and will be produced in February 2016. This 128-bit secure elliptic curve is to be generated following the full methodology described in the technical paper and demonstrated in the tutorial to generate the Three Cents Curve. In particular, by committing publicly on the (deterministic) process and the list of draws before they actually happen, our methodology is designed so that nobody (even us!) can put a trap in the Million Dollar Curve.
Our objective is for the Million Dollar Curve to inspire confidence to the greatest number. In that sense, we want to integrate comments we receive in the methodology before committing on the final methodology, final source code and the lottery draws we will use.
You can direct any comment you have to us and we will gladly listen. Email us!
In what follows, we describe how we will generate the MDCurve201601 Curve (Million Dollar Curve of January 2016).
Our methodology can easily be adapted (and reproducible by anyone) for new curves with possibly different specifications (e.g. not an Edwards curve or aiming at 256 bits of security), and of course new lottery draws.
We will likely generate new Million Dollar Curves in the future on this website as needed.
Timeline to generate the MDCurve201601 Curve
In order for the Million Dollar Curve to win its spur, we greatly welcome any comment to improve the methodology we propose.
Email us!On January 27th 2016, we presented a full document (a text file) that describes the generation of Million Dollar Curve of January 2016 (named MDCurve201601), the list of security criteria we consider, and the acceptable set of parameters.
This design text file can be downloaded here: 2016_01_27_million_dollar_curve.txt
The SHA256 hash of this file is
We commited on this design text file in the following ways:
X509v3 Subject Alternative Name
).
#MDCurve201601 SHA256
e9dd4baf0d351b5a64c59ed6b1efd3108094b3585e17a0e5350fb200500058d9 https://cryptoexperts.github.io/million-dollar-curve/specifications/mdcurve_201601/2016_01_27_million_dollar_curve.txt
On January 29th 2016, we commited on a text file containing a list of future draws (starting on February 1st, 2016), a clear pointer to the aforementioned design (Phase II), and a source code that deterministically computes the seed from the listed draws.
This design text file can be downloaded here: 2016_01_29_million_dollar_curve_seeding.txt
The SHA256 hash of this file is
We commited on this design text file in the following ways:
X509v3 Subject Alternative Name
).
#MDCurve201601 SHA256
f8bdb5bd4957a2d65b567378bb32744d0d0573a77e4ef0247311a5a4b98744da https://cryptoexperts.github.io/million-dollar-curve/specifications/mdcurve_201601/2016_01_29_million_dollar_curve_seeding.txt
During this period, the draws on which we committed on in Phase III took place, and the full list of results was gathered.
On February 15th 2016, we published the final list of draw results. This list is available here:
Among the 260 draws we committed on during Phase III, only 5 did not take place:
2016-02-08_br_quina
, 2016-02-08_br_lotofacil
, 2016-02-09_br_quina
, and
2016-02-09_br_dupla_sena
), which were not drawn probably because of the Brazilian Carnival (February 5-February 10 in 2016).2016-02-03_br_mega_sena
), which actually took place on February 2.On February 15th 2016, the required draws we committed on were available, and the full list of results was made public.
Using the source code committed on in Phase III, we generated the seed from the full list of results: We obtained the following file, containing the seed: in_02.json
Using the source code committed on in Phase II and the aforementioned seed, we generated the BBS parameters, the prime field, and the MDCurve201601 curve as follows:
We obtained the following file, containing the BBS parameters: in_03.json
We obtained the following file, containing the prime for the underlying field: in_04.json
On the 29535th iteration, we obtained the following file, containing the parameters for the Million Dollar Curve: out.json
See below for a summary of what we obtained!
The Million Dollar Curve - MDCurve201601
The Million Dollar Curve (MDC201601) is an elliptic curve in Edwards form, suited for cryptographic applications, providing 128 bits of security. It comes with a base point generating a large subgroup. This curve was generated using a novel and (hopefully) unimpeachable process, allowing anyone to make sure that no backdoor could have been introduced. Here is a small list of the features of the million dollar curve:
The parameters of the Million Dollar Curve are:
Here are a few more properties of the Million Dollar Curve:
In this table, one can find an exhaustive list of lotteries we use, that is lotteries for which we could easily access an up-to-date archive of draws. Each lottery picks a number \(m\) among \(n\) numbers, and we specify the resulting entropy per draw and the number of draws per week.
Lottery name | \(m\) | \(n\) | Entropy | Weekly draws | Weekly entropy |
---|---|---|---|---|---|
Australian Monday Lotto | 6 | 45 | 22.95 | 1 | 22.95 |
Australian OZ Lotto | 7 | 45 | 25.43 | 1 | 25.43 |
Australian Powerball | 6 | 40 | 21.87 | 1 | 21.87 |
Australian Saturday Lotto | 6 | 45 | 22.95 | 1 | 22.95 |
Australian Wednesday Lotto | 6 | 45 | 22.95 | 1 | 22.95 |
Belgian Lotto | 6 | 45 | 22.95 | 2 | 45.90 |
Brasilian Dupla-Sena | 6 | 50 | 23.92 | 2 | 47.84 |
Brasilian Lotofácil | 15 | 25 | 21.64 | 3 | 64.92 |
Brasilian Mega-Sena | 6 | 60 | 25.57 | 2 | 51.14 |
Brasilian Quina | 5 | 80 | 24.51 | 6 | 147.06 |
Canadian Daily Keno (Midday Draw) | 20 | 70 | 57.16 | 7 | 400.12 |
Canadian Daily Keno (Evening Draw) | 20 | 70 | 57.16 | 7 | 400.12 |
Canadian Loto 649 (Main Draw) | 6 | 49 | 23.73 | 2 | 47.46 |
Canadian Loto Max (Main Draw) | 7 | 49 | 26.35 | 1 | 26.35 |
Canadian Lottario | 6 | 45 | 22.95 | 1 | 22.95 |
Swiss Loto | 6 | 42 | 22.32 | 2 | 44.64 |
German Euro Jackpot | 5 | 50 | 21.01 | 1 | 21.01 |
German Keno | 20 | 70 | 57.16 | 7 | 400.12 |
German Loto | 6 | 49 | 23.73 | 2 | 47.46 |
Spanish Bonoloto | 6 | 49 | 23.73 | 6 | 142.38 |
Spanish El Gordo | 5 | 54 | 21.59 | 1 | 21.59 |
Spanish La Primitiva | 6 | 49 | 23.73 | 2 | 47.46 |
European Euro Millions | 5 | 50 | 21.01 | 2 | 42.02 |
French Keno (Noon) | 20 | 70 | 57.16 | 7 | 400.12 |
French Keno (Evening) | 20 | 70 | 57.16 | 7 | 400.12 |
French Loto | 5 | 49 | 20.86 | 3 | 62.58 |
Italian SuperEnalotto | 6 | 90 | 29.21 | 3 | 87.63 |
Mauritius Loto | 6 | 40 | 21.87 | 1 | 21.87 |
Dutch Lotto (Standard 1st trecking draws) | 6 | 45 | 22.95 | 1 | 22.95 |
New Zealand Keno (1st daily draw - 10AM) | 20 | 80 | 61.61 | 7 | 431.27 |
New Zealand Keno (2nd daily draw - 1PM) | 20 | 80 | 61.61 | 7 | 431.27 |
New Zealand Keno (3rd daily draw - 3PM) | 20 | 80 | 61.61 | 7 | 431.27 |
New Zealand Keno (4th daily draw - 6PM) | 20 | 80 | 61.61 | 7 | 431.27 |
New Zealand Lotto | 6 | 40 | 21.87 | 2 | 43.74 |
UK Health Lottery (Saturday £1 draw) | 5 | 50 | 21.01 | 1 | 21.01 |
US Hot Lotto | 5 | 47 | 20.54 | 2 | 41.08 |
US Mega Millions | 5 | 75 | 24.04 | 2 | 48.08 |
US NY Cash 4 Life | 5 | 60 | 22.38 | 2 | 44.76 |
US NY Lotto | 6 | 59 | 25.42 | 2 | 50.84 |
US Powerball | 5 | 69 | 23.42 | 2 | 46.84 |
US Wild Card | 5 | 33 | 17.85 | 2 | 35.70 |
Total | \(\approx\)5189 |
Since the publication of this project, we have received many questions and saw many reactions on, e.g., Twitter. We plan to answer most of them on this webpage.
Yes and no.
The Million Dollar Curve in itself is just another safe curve, but it is generated using a novel process. This process is detailed in our technical paper and allows to generate parameters everyone can trust for new cryptosystem standards, but also in any other situation requiring verifiable randomness.
No.
We, at CryptoExperts, actually use Curve25519 and recommend it to our partners. Yet, we think that people should not rely on the same few safe curves that are currently out. Our methodology allows to easily produce safe alternatives.
Curve25519 was designed to be as fast as possible, with no security compromise. This is both a strength and a potential weakness:
For applications where speed is paramount, Curve25519 is probably the best option. But for most applications, where losing a little on the efficiency side is "not a big deal", Million Dollar Curve is probably the safest choice.
This is not an issue.
Our parameter generation process was specifically designed to avoid this kind of problem. As explained in Section 4.4 of our technical paper, in order to manipulate the parameter generation, an adversary has to rig all the last lottery draws (what we call the "Last draw attack"). We mitigate this risk by relying on independent lotteries from various countries around the world.
Yes and no.
Most national lotteries follow a strict protocol which is specifically designed to avoid manipulations (certified drawing machines, supervision of a bailiff, legal process, etc.). It is pretty obvious that in the past some lotteries have been manipulated, but manipulations with financial motive are not a concern for us (at most, a few bits of entropy are lost). Besides, as explained in the previous answer, an adversary would have to manipulate all the last lottery draws.
These archives are usually duplicated in several places over the Internet or sometimes printed in newspapers. If at a given time in the future the result of a drawing becomes completely unavailable, verification will become impossible.
However, the lotteries that have been selected are well established and will most certainly continue to exist for some time. During this period, everyone will be able to fully verify/re-generate the Million Dollar Curve, which in itself is a convincing argument for later use.
You can probably verify that lotteries from your own country actually exist: you might even have played them before hearing about Million Dollar Curve. Your friends in Mauritius, Canada, and New Zealand can certainly confirm the same thing.
Besides, lotteries are such popular games that "faking" one in a convincing way is probably impossible without being noticed at some point.
This situation is already taken into account in our generation process and the scripts we provide, so this is not a problem. The missing draws are simply ignored (see, for example, section How to treat missing draws
in 2015_09_three_cents_curve_standardization.txt)